home *** CD-ROM | disk | FTP | other *** search
- // ===========================================================================
-
- #include "MultiMonitorApp.h"
-
- #include <PP_DebugMacros.h>
-
- #include <LGrowZone.h>
- #include <PP_Messages.h>
- #include <PP_Resources.h>
- #include <UDrawingState.h>
- #include <UMemoryMgr.h>
- #include <URegistrar.h>
- #include <UEnvironment.h>
- #include <UAttachments.h>
- #include <LDocument.h>
- #include <LMenuBar.h>
- #include <LModelDirector.h>
- #include <UScreenPort.h>
- #include <LComparator.h>
- #include <LCMAttachment.h>
- #include <UCMMUtils.h>
- #include <LUndoer.h>
- #include <LMenu.h>
- #include <UDesktop.h>
-
- #include <UStandardDialogs.h>
- #if PP_StdDialogs_Option == PP_StdDialogs_Conditional
- #include <UConditionalDialogs.h>
- #endif
-
- #include <UControlRegistry.h>
-
- #include <LDebugStream.h>
-
- #include <UDebugNew.h>
- #include <UDebugUtils.h>
- #include <UHeapUtils.h>
- #include <UMemoryEater.h>
- #include <UOnyx.h>
- #include <UProcess.h>
- #include <UVolume.h>
-
- #if PP_Debug
- #include <LSIOUXAttachment.h> // Only needed for LDebugStream
-
- #include <LDebugMenuAttachment.h>
- #include <LCommanderTree.h>
- #include <LPaneTree.h>
- #include <LTreeWindow.h>
- #endif
-
- #include <LWindow.h>
- #include <LPrintout.h>
- #include <LPlaceHolder.h>
-
- #include "MultiMonitorDoc.h"
- #include "MultiMonitorController.h"
-
- #include <Appearance.h>
-
- #if PP_Debug
- #include "MetroNubUtils.h"
- #endif
-
- #include <new>
-
- #include "UMiscUtils.h"
-
- // ---------------------------------------------------------------------------
- // Prototypes
-
- void AppMain(); // main loop
- void PP_NewHandler() throw (PP_STD::bad_alloc); // defined in PPDebug_New.cp
-
- const CommandT cmd_DoTest = FOUR_CHAR_CODE('teSt');
-
-
- // ===========================================================================
- // • main
- // ===========================================================================
-
- int main()
- {
- // First things first. Install a new_handler.
- (void)PP_STD::set_new_handler(PP_NewHandler);
-
- // Don't let exceptions propagate outside of main
- try {
- AppMain();
- } catch (...) {
- SignalStringLiteral_("Exception caught in main");
- }
-
- return 0;
- }
-
-
- // ---------------------------------------------------------------------------
- // • AppMain
- // ---------------------------------------------------------------------------
-
- void AppMain()
- {
- #if PP_Debug
-
- // If under the debugger, use the debugger for everything
- // (throw, signal, DebugNew), else use alerts.
-
- if (AmIBeingMWDebugged()) {
-
- UDebugging::SetDebugThrow(debugAction_Debugger);
- UDebugging::SetDebugSignal(debugAction_Debugger);
-
- } else {
-
- // Not under the MW Debug, so use alerts. If you use
- // another debugger, you could set this up the same way. Point
- // is to use the debugger's facilities when under the debugger,
- // else alerts.
-
- UDebugging::SetDebugThrow(debugAction_Alert);
- UDebugging::SetDebugSignal(debugAction_Alert);
-
- // Use our own error handler for DebugNew which uses alerts
- // instead of DebugStr calls.
-
- PP_DebugNewInstallPPErrorHandler_();
- }
-
- #else
- // In final build mode so nothing should be seen. These are
- // commented out because gDebugThrow and gDebugSignal are
- // initialized to debugAction_Nothing -- assignment here is
- // unnecessary (but left in as a comment for illustration).
-
- UDebugging::SetDebugThrow(debugAction_Nothing);
- UDebugging::SetDebugSignal(debugAction_Nothing);
-
- #endif
-
- // Clean up any "leaks" that might have occured at static
- // initialization time.
- {
- SLResetLeaks_();
- DebugNewForgetLeaks_();
- }
-
-
- // Normal initializations
- InitializeHeap(5);
- UQDGlobals::InitializeToolbox(&qd);
- ::InitCursor();
- ::FlushEvents(everyEvent, nil);
-
- // Check Debugging environment
- #if PP_Debug
- UDebugUtils::CheckEnvironment();
- #endif
-
- // Install a GrowZone to catch low-memory situations
- LGrowZone* theGZ = NEW LGrowZone(20000);
- ValidateObject_(theGZ);
- SignalIf_(theGZ->MemoryIsLow());
-
- // Create the application object and run. The scope of
- // the object is limited as we need to control when
- // the object's destructor is called (in relation to
- // the code that follows it).
- {
- MultiMonitorApp theApp;
- theApp.Run();
- }
-
- #if PP_Debug
-
- // This cleanup isn't necessary (they are items that are to
- // remain for the duration of the application's run time. When
- // the app quits and the Process Manager reclaims the heap,
- // the memory occupied by these items will be released). This
- // is just done to keep things like DebugNew and Spotlight
- // quiet.
-
- LMenuBar* theBar = LMenuBar::GetCurrentMenuBar();
- delete theBar;
-
- URegistrar::DisposeClassTable();
-
- LPeriodical::DeleteIdlerAndRepeaterQueues();
-
- UMemoryEater::DeleteMemoryLists();
-
- LModelDirector* theDirector = LModelDirector::GetModelDirector();
- delete theDirector;
-
- LModelObject::DestroyLazyList();
-
- UScreenPort::Dispose();
-
- LComparator* theCompare = LComparator::GetComparator();
- delete theCompare;
-
- LLongComparator* theLongCompare = LLongComparator::GetComparator();
- delete theLongCompare;
-
- DisposeOf_(theGZ);
-
- #endif
-
- DebugNewReportLeaks_();
- }
-
-
- // ---------------------------------------------------------------------------
- // • MultiMonitorApp [public]
- // ---------------------------------------------------------------------------
- // Application object constructor
-
- MultiMonitorApp::MultiMonitorApp()
- {
- // Register ourselves with the Appearance Manager
- if (UEnvironment::HasFeature(env_HasAppearance)) {
- ::RegisterAppearanceClient();
- }
-
- RegisterClasses();
-
- // Preload facilities for the Standard Dialogs
- PP_StandardDialogs::Load();
-
- // Require at least Navigation Services 1.1. See comments
- // above SetTryNavServices in UConditionalDialogs.cp for why
- // you might wish to do this.
- #if PP_StdDialogs_Option == PP_StdDialogs_Conditional
- UConditionalDialogs::SetTryNavServices(0x01108000);
- #endif
-
- // Initialize contextual menus
- UCMMUtils::Initialize();
- AddAttachment(NEW LCMAttachment);
- }
-
-
- // ---------------------------------------------------------------------------
- // • ~MultiMonitorApp [public, virtual]
- // ---------------------------------------------------------------------------
- // Application object destructor
-
- MultiMonitorApp::~MultiMonitorApp()
- {
- // Clean up after Standard Dialogs
- PP_StandardDialogs::Unload();
- }
-
-
- // ---------------------------------------------------------------------------
- // • StartUp [protected, virtual]
- // ---------------------------------------------------------------------------
- // Perform an action in response to the Open Application AppleEvent.
- // Here, issue the New command to open a window.
-
- void
- MultiMonitorApp::StartUp()
- {
- ObeyCommand(cmd_New, nil);
- }
-
-
- // ---------------------------------------------------------------------------
- // • ObeyCommand [public, virtual]
- // ---------------------------------------------------------------------------
- // Respond to Commands. Returns true if the Command was handled, false if not.
-
- Boolean
- MultiMonitorApp::ObeyCommand(
- CommandT inCommand,
- void * ioParam)
- {
- Boolean cmdHandled = true; // Assume we'll handle the command
-
- switch (inCommand) {
-
- #if PP_Debug
- case cmd_DoTest: {
- DoTest();
- break;
- }
- #endif
-
- default: {
- cmdHandled = LDocApplication::ObeyCommand(inCommand, ioParam);
- break;
- }
- }
-
- return cmdHandled;
- }
-
-
- // ---------------------------------------------------------------------------
- // • FindCommandStatus [public, virtual]
- // ---------------------------------------------------------------------------
- // Determine the status of a Command for the purposes of menu updating.
-
- void
- MultiMonitorApp::FindCommandStatus(
- CommandT inCommand,
- Boolean& outEnabled,
- Boolean& outUsesMark,
- UInt16& outMark,
- Str255 outName)
- {
- switch (inCommand) {
-
- #if PP_Debug
- case cmd_DoTest: {
- outEnabled = true;
- break;
- }
- #endif
-
- default: {
- LDocApplication::FindCommandStatus(inCommand, outEnabled,
- outUsesMark, outMark, outName);
- break;
- }
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // • Initialize
- // ---------------------------------------------------------------------------
- // Here we do a few interesting things.
- //
- // 1. Flush any pending events. I have seen times where if you launch
- // your app and then immediately hit a menu key combo to cause
- // a window to come up, that can crash! Flushing any such pending
- // events before you're ready to even process them seems to
- // remedy that.
- //
- // 2. We create our debug menu attachment. We only need this for the
- // debug build, so we conditionally compile it out.
- //
- // 3. We check the version of your application. A bit unnecessary
- // perhaps, but I always found it nice towards ensuring I didn't
- // forget to update my constants and 'vers' resource. Only necessary
- // in the debug build.
- //
- // 4. You could do other things here as well: append items to your
- // Help menu, Apple Guide initialization, creating your preferences
- // object, etc.
-
- void
- MultiMonitorApp::Initialize()
- {
- LDocApplication::Initialize();
-
- ::FlushEvents(everyEvent, nil);
- }
-
- // ---------------------------------------------------------------------------
- // • MakeNewDocument [protected, virtual]
- // ---------------------------------------------------------------------------
- // This method creates a new document and installs it into the application's
- // Apple Event Object Model hierarchy.
-
- LModelObject*
- MultiMonitorApp::MakeNewDocument()
- {
- // Make a new empty document.
- MultiMonitorDoc * theDoc = NEW MultiMonitorDoc(this);
- ValidateObject_(theDoc);
-
- NEW MultiMonitorController();
-
- return theDoc;
- }
-
-
- // ---------------------------------------------------------------------------
- // • RegisterClasses [protected]
- // ---------------------------------------------------------------------------
- // To reduce clutter within the Application object's constructor, class
- // registrations appear here in this seperate function for ease of use.
-
- void
- MultiMonitorApp::RegisterClasses()
- {
- // Register debugging classes
- #if PP_Debug
- RegisterClass_(LCommanderTree);
- RegisterClass_(LPaneTree);
- RegisterClass_(LTreeWindow);
- #endif
-
- // Register core PowerPlant classes.
- RegisterClass_(LWindow);
- RegisterClass_(LPrintout);
- RegisterClass_(LPlaceHolder);
- RegisterClass_(LKeyScrollAttachment);
- RegisterClass_(LColorEraseAttachment);
- RegisterClass_(LCMAttachment);
- RegisterClass_(LUndoer);
-
- // Register the Appearance Manager/GA classes. You may want
- // to remove this use of UControlRegistry and instead perform
- // a "manual" registration of the classes. This cuts down on
- // extra code being linked in and streamlines your app and
- // project. However, use UControlRegistry as a reference/index
- // for your work, and ensure to check UControlRegistry against
- // your registrations each PowerPlant release in case
- // any mappings might have changed.
-
- UControlRegistry::RegisterClasses();
- }
-
-
- // ---------------------------------------------------------------------------
- // • DoTest [public]
- // ---------------------------------------------------------------------------
- // A handy place to insert test code (i.e. you want to try some code out
- // and just need a place to put it).
-
- void
- MultiMonitorApp::DoTest()
- {
- SignalStringLiteral_("Insert your test code here");
- }